using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace CincinnatiLibraryCheckAvailability
{
    public static class GlobalHotkey
    {
        // Windows API functions and constants
        [DllImport("user32", SetLastError = true)]
        private static extern int RegisterHotKey(IntPtr hwnd, int id, int fsModifiers, int vk);
        [DllImport("user32", SetLastError = true)]
        private static extern int UnregisterHotKey(IntPtr hwnd, int id);
        [DllImport("kernel32", SetLastError = true)]
        private static extern short GlobalAddAtom(string lpString);
        [DllImport("kernel32", SetLastError = true)]
        private static extern short GlobalDeleteAtom(short nAtom);

        private const int MOD_ALT = 1;
        private const int MOD_CONTROL = 2;
        private const int MOD_SHIFT = 4;
        private const int MOD_WIN = 8;

        // the id for the hotkey

        // register a global hot key
        internal static bool Register(HotKey hotkey)
        {
            try
            {
                // use the GlobalAddAtom API to get a unique ID (as suggested by MSDN docs)
                if (hotkey.id == 0)
                {
                    string atomName = Thread.CurrentThread.ManagedThreadId.ToString("X8") + hotkey;
                    hotkey.id = GlobalAddAtom(atomName);

                    if (hotkey.id == 0)
                    {
                        throw new Exception("Unable to generate unique hotkey ID. Error code: " +
                           Marshal.GetLastWin32Error().ToString());
                    }
                }
                // register the hotkey, throw if any error
                if (RegisterHotKey(hotkey.Handle, hotkey.id, (int)hotkey.Modifiers, (int)hotkey.Key) == 0)
                {
                    throw new Exception("Unable to register hotkey. Error code: " + Marshal.GetLastWin32Error()
                       .ToString());
                }
            }
            catch (Exception)
            {
                // clean up if hotkey registration failed
                Unregister(hotkey);
                return false;
            }
            return true;
        }

        // unregister a global hotkey
        internal static void Unregister(HotKey hotkey)
        {
            if (hotkey.id != 0)
            {
                UnregisterHotKey(hotkey.Handle, hotkey.id);
                // clean up the atom list
                GlobalDeleteAtom(hotkey.id);
                hotkey.id = 0;
            }
        }
    }
}